dojo.provide("uws.drawing.Connection");

dojo.declare('uws.drawing.Connection',null,{
	/*
		The superclass of all connections.
	*/
	
	//from the data store
	id:null,
	umltype:null,
	cardinality1: null,
	cardinality2: null,
	shape1_dir:null,
	shape2_dir:null,
	
	//visual representation
	shapeCon:null,
	shapeCon2:null,
	shapeCon3:null,
	shapeCon4:null,
	shapeCon5:null,
	shapeCon6:null,
	shapeCon7:null,
	shapeCon8:null,
	shapeCon9:null,
	group:null,
	x1:null,
	y1:null,
	x2:null,
	y2:null,
	stereotype_shape:null,
	
	//original connection point position
	con_x1:null,
	con_y1:null,
	con_x2:null,
	con_y2:null,
	
	//movement monitoring
	shape1_monitor:null,
	shape2_monitor:null,
	
	//destroy
	focusHandle:null,
	constructor: function(id, surface, shape1, shape1_dir, shape2, shape2_dir){
		this.id = id;
		this.stereotype="";
		this.group = surface.createGroup();
		this.cardinality1 = 1;
		this.cardinality2 = 1;
		
		var matrix = shape1.shape_moveable.shape.matrix;
		if(matrix == null) {
			matrix = {
				dx: 0,
				dy: 0
			};
		}
		if(shape1_dir=="top"){
			this.x1 = shape1.top_con.shape.cx + matrix.dx;
			this.y1 = shape1.top_con.shape.cy + matrix.dy;
		}else if(shape1_dir=="bottom"){
			this.x1 = shape1.bottom_con.shape.cx + matrix.dx;
			this.y1 = shape1.bottom_con.shape.cy + matrix.dy;
		}else if(shape1_dir=="right"){
			this.x1 = shape1.right_con.shape.cx + matrix.dx;
			this.y1 = shape1.right_con.shape.cy + matrix.dy;
		}else if(shape1_dir=="left"){
			this.x1 = shape1.left_con.shape.cx + matrix.dx;
			this.y1 = shape1.left_con.shape.cy + matrix.dy;
		}
		
		this.con_x1=this.x1 - matrix.dx;
		this.con_y1=this.y1 - matrix.dy;
		
		matrix = shape2.shape_moveable.shape.matrix;
		if(matrix == null) {
			matrix = {
				dx: 0,
				dy: 0
			};
		}
		if(shape2_dir=="top"){
			this.x2 = shape2.top_con.shape.cx + matrix.dx;
			this.y2 = shape2.top_con.shape.cy + matrix.dy;
		}else if(shape2_dir=="bottom"){
			this.x2 = shape2.bottom_con.shape.cx + matrix.dx;
			this.y2 = shape2.bottom_con.shape.cy + matrix.dy;
		}else if(shape2_dir=="right"){
			this.x2 = shape2.right_con.shape.cx + matrix.dx;
			this.y2 = shape2.right_con.shape.cy + matrix.dy;
		}else if(shape2_dir=="left"){
			this.x2 = shape2.left_con.shape.cx + matrix.dx;
			this.y2 = shape2.left_con.shape.cy + matrix.dy;
		}
		
		this.con_x2=this.x2 - matrix.dx;
		this.con_y2=this.y2 - matrix.dy;
		
		try{
			this.group.getNode().style.cursor="pointer";
		}catch(e){};
		this.focusHandle = this.group.connect("onclick",this,"_publishProperties");
	},
	destroy:function(){
		this.group.removeShape();
		dojo.disconnect(this.shape1_monitor);
		dojo.disconnect(this.shape2_monitor);
		this.group.disconnect(this.focusHandle);
	},
	_publishProperties:function(item){
		dataStore.fetchItemByIdentity({
			identity: this.id,
			scope: surfaceManager,
			onItem:function(component){
				var attr = dataStore.getAttributes(component);
				var val = [];
				for(var i=0;i<attr.length;i++){
					val[i] = dataStore.getValue(component, attr[i], "");
				}
				dojo.publish("uwsProperties",[{
					attributes:attr,
					values:val
				}]);
			},
			onError:function(error){
				console.debug(error);
			}
		});
	},
	getArrowCoordinatesNoSlope:function(x1,y1,x2,y2){
		var dist = this._getDistance(x1, y1, x2, y2)/16;
		if(y2>y1){		//arrow is downwards
			if(dist>11){
				dist = 11;
			}else if(dist<6){
				dist = 6;
			}
			
			return [{x:x2,y:y2-dist},{x:x2-5,y:y2-dist},{x:x2+5,y:y2-dist}];
		}else{
			if(dist>11){
				dist = 11;
			}else if(dist<6){
				dist = 6;
			}
			
			return [{x:x2,y:y2+dist},{x:x2-5,y:y2+dist},{x:x2+5,y:y2+dist}];
		}
	},
	getArrowCoordinates:function(point1, point2){
		var x1,y1,x2,y2;
		
		if(!point1) x1 = this.x1;
		else x1 = point1.x;
		
		if(!point1) y1 = this.y1;
		else y1 = point1.y;
		
		if(!point2) x2 = this.x2;
		else x2 = point2.x;
		
		if(!point2) y2 = this.y2;
		else y2 = point2.y;
		
		var retVal = [{x:0,y:0},{x:0,y:0},{x:0,y:0}];
		
		if((Math.abs(x2-x1)<40) || (Math.abs(x1-x2)<40)){
			return this.getArrowCoordinatesNoSlope(x1,y1,x2,y2);
		}
		
		if((y2-y1)==0){
			y2+=1;
		}
		
		var slope1 = (y2 - y1) / (x2 - x1);
		var slope2 = -1/slope1;
		var dist = this._getDistance(x1, y1, x2, y2)/16;
		
		if(dist>11){
			dist=11;
		}else if(dist<6){
			dist = 6;
		}
		
		if(x2>x1){
			var temp = x2-dist; 
			if(temp<=x1+5) temp = (x2+x1)/2
			
			var y3 = this._getY(x2, y2, temp, slope1);
			retVal[0] = {x: x2 - dist, y: y3};		//at the line
		}else{
			var temp = x2+dist; 
			if(temp>=x1-5) temp = (x2+x1)/2
			
			var y3 = this._getY(x2, y2, x2 + dist, slope1);
			retVal[0] = {x: x2 + dist, y: y3};		//at the line
		}
		
		dist2 = dist/2;
		var temp1 = this._getX(retVal[0].x, retVal[0].y, retVal[0].y + (dist2), slope2);
		var temp2 = this._getX(retVal[0].x, retVal[0].y, retVal[0].y - (dist2), slope2);
		
		retVal[1] = {x: temp1, y: retVal[0].y + dist2};
		retVal[2] = {x: temp2, y: retVal[0].y - dist2};
		
		return retVal;
	},
	_getY:function(x2, y2, x, slope){
		return ((slope * (x - x2)) + y2);
	},
	_getX:function(x2,y2, y, slope){
		return ((y-y2)/slope) + x2;
	},
	_getDistance:function(x1,y1,x2,y2){
		return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
	}
});